#ifndef _YSTR_H
#define _YSTR_H
#include <tool/ydefine.h>

/** Function pointers struct, use externally */
typedef struct strFn *strFn;
/** Data struct, use internally */
typedef struct strFnData *strFnData;

/** struct of string function pointers */
struct strFn {
  /*--- data ---*/
  strFnData d;
  /*--- function pointers ---*/
  /** Free a <code>strFn</code>, free up the memory.
  @param fnP pass in the address of <code>strFn</code> to be free.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*freeFn)(strFn *fnP);
  /* specific operation */
  /** Compares the first <code>n</code> bytes of 
  <code>str1</code> and <code>str2</code>. 
  Does not stop comparing even after the null character 
  (it always checks <code>n</code> characters).
  @param str1 the first string.
  @param str2 the second string.
  @param n the number of characters to compare or 
    the length of the string to compare.
  @return Returns zero if the first <code>n</code> bytes of 
    <code>str1</code> and <code>str2</code> are equal. 
    Returns less than zero or greater than zero 
    if <code>str1</code> is less than or greater than 
    <code>str2</code> respectively.
  */
  int (*memcmpIgnoreCase)(const char *str1, const char *str2, size_t n);
  /** Searches for the last occurrence of the character <code>c</code> 
  (an unsigned char) to <code>n</code> bytes of characters. 
  Starting from pointer <code>ptrEnd</code>
  moving in reverse right to left. Slower in c version.
  <p>WARNING: Thus the behaviour of this function is NOT the same as
  ANSI C library <code>strrchr, i.e.
  char *strrchr(const char *str, int c); </code>
  </p>
  <pre>ANSI C provides memchr, which scans memory using ascending      
  addresses (to the right), starting from the specified           
  address.  However, there's no equivalent reverse scan
  (right to left) function.
  </pre>
  @param ptrEnd pointer to the end of the character array.
  @param c the character to find.
  @param n the number of characters to compare or 
    the length of the character array to compare, 
    including char at <code>ptrEnd</code>.
  @return Returns a pointer pointing to the last matching character, 
    or null if no match was found.
  */
  void *(*memrchr)(const void *str, int c, size_t n);
  /** Test if string is numbers.
  @param str the string.
  @return true or false.
  */
  boolean (*isNumbers)(const char *str);
  /** Test if string is numbers, 
  provide the exact length of string to test.
  @param str the string.
  @param strLen the length of string to test.
  @return true or false.
  */
  boolean (*isNumbersWithLen)(const char *str, int strLen);
  /** Return concaternation of two string.
  Concaternate <code>str2</code> to the end of <code>str1</code>, 
  not including <code>str1</code>'s <code>NULL</code> char.
  The new string with a proper <code>NULL</code> end char is returned.
  <p>Since this string is <code>malloc(..)</code>, to avoid memory leak
  it should be freed when no longer needed with a call to 
  <code>free(void *)</code>.
  </p>
  @param fn the <code>strFn</code> to use.
  @param str1 the first string.
  @param str2 the second string.
  @return new string or <code>NULL</code> if unsuccessful.
  */
  char *(*cat)(const strFn fn, const char *str1, const char *str2);
  /** Return concaternation of two string and its' new length.
  Concaternate <code>str2</code> to the end of <code>str1</code>, 
  not including <code>str1</code>'s <code>NULL</code> char.
  The new string with a proper <code>NULL</code> end char is returned and 
  its length is given in <code>newStrLen</code>.
  <p>Since this string is <code>malloc(..)</code>, to avoid memory leak
  it should be freed when no longer needed with a call to 
  <code>free(void *)</code>.
  </p>
  @param fn the <code>strFn</code> to use.
  @param str1 the first string.
  @param str2 the second string.
  @param newStrLen length of the new string.
  @return new string or <code>NULL</code> if unsuccessful.
  */
  char *(*catWithLen)(const strFn fn, const char *str1, const char *str2, 
      unsigned int newStrLen);
  /** Duplicate a string.
  <p>Since this string is <code>malloc(..)</code>, to avoid memory leak
  it should be freed when no longer needed with a call to 
  <code>free(void *)</code>.
  </p>
  @param fn the <code>strFn</code> to use.
  @param str the string.
  @return new string or <code>NULL</code> if unsuccessful.
  */
  char *(*clone)(const strFn fn, const char *str);
  /** Duplicate a string with this length.
  <p>Since this string is <code>malloc(..)</code>, to avoid memory leak
  it should be freed when no longer needed with a call to 
  <code>free(void *)</code>.
  </p>
  @param fn the <code>strFn</code> to use.
  @param str the string.
  @param strLen the length of the string to copy.
  @return new string or <code>NULL</code> if unsuccessful.
  */
  char *(*cloneLen)(const strFn fn, const char *str, const size_t strLen);
  /** Duplicate a string and replace any string 
  that has a valid escape sequence chars.
  "\ddd" octal digits and "\xdd" hexadecimal digit is not handled.
  e.g. 2 chars "\n" in a string becomes 1 char '\n'
  <p>Since this string is <code>malloc(..)</code>, to avoid memory leak
  it should be freed when no longer needed with a call to 
  <code>free(void *)</code>.
  </p>
  @param fn the <code>strFn</code> to use.
  @param str the string.
  @return new string or <code>NULL</code> if unsuccessful.
  */
  char *(*cloneES)(const strFn fn, char *str);
  /** Duplicate a string with this length and replace any string 
  that has a valid escape sequence chars. 
  "\ddd" octal digits and "\xdd" hexadecimal digit is not handled.
  e.g. 2 chars "\n" in a string becomes 1 char '\n'
  <p>Since this string is <code>malloc(..)</code>, to avoid memory leak
  it should be freed when no longer needed with a call to 
  <code>free(void *)</code>.
  </p>
  @param fn the <code>strFn</code> to use.
  @param str the string.
  @param strLen the length of the string to copy.
  @return new string or <code>NULL</code> if unsuccessful.
  */
  char *(*cloneESLen)(const strFn fn, char *str, const size_t strLen);
  /** Attempt to resize (realloc) the character string, thus freeing some memory.
  @param fn the <code>strFn</code> to use.
  @param ptr the character array.
  @return the resized character array OR the original array if failure occurs.
  */
  char *(*resize)(const strFn fn, char *ptr);
  /** Attempt to resize (realloc) the character string, thus freeing some memory.
  @param fn the <code>strFn</code> to use.
  @param ptr the character array.
  @param n the length of the array to be resize to.
  @return the resized character array OR the original array if failure occurs.
  */
  char *(*resizeLen)(const strFn fn, char *ptr, const unsigned int n);
  /** Return the pointer to the left position in the 
  character array that is not a space or horizontal tab.
  @param ptr the character array.
  @param n the length of the array to be searched.
  @return a pointer to the left position in the 
    character array that is not a space or horizontal tab.
  */
  char *(*trimLeft)(char *ptr, const unsigned int n);
  /** Remove white space in a string and return a new string.
  Since this string is <code>malloc(..)</code>, to avoid memory leak
  it should be freed when no longer needed with a call to 
  <code>free(void *)</code>.
  @param fn the <code>strFn</code> to use.
  @param str the string.
  @return new string or <code>NULL</code> if unsuccessful.
  */
  char *(*removeWhiteSpace)(const strFn fn, const char *str);
  /** Remove white space in a string beginning & 
  ending with these position and return a new string.
  Since this string is <code>malloc(..)</code>, to avoid memory leak
  it should be freed when no longer needed with a call to 
  <code>free(void *)</code>.
  @param fn the <code>strFn</code> to use.
  @param str the string.
  @param charStart start position of str.
  @param charEnd end position of str.
  @return new string or <code>NULL</code> if unsuccessful.
  */
  char *(*removeWhiteSpaceNPos)(const strFn fn, const char *str, 
      const int posStart, const int posEnd);
};

/** Create a <code>strFn</code> that provide ystr function pointers.
@return the struct of ystr function pointers
  or <code>NULL</code> if failure.
*/
strFn ystr_createFn(void);

#endif /* _YSTR_H */
